package com.emperor.employee.app;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.hibernate.Session;
import org.hibernate.criterion.Expression;

import com.emperor.core.app.App;
import com.emperor.core.app.AppBase;
import com.emperor.core.app.AppConstant;
import com.emperor.employee.logic.Employee;
import com.emperor.employee.logic.EmployeeModel;
import com.emperor.role.logic.Role;
import com.emperor.role.logic.RoleModel;
import com.emperor.user.logic.User;
import com.emperor.user.logic.UserModel;
import com.emperor.util.HibernateUtil;
import com.swtdesigner.SWTResourceManager;

public class EmployeeAppMgm extends AppBase implements App {

	private Combo combo;
	protected Shell shell;
	protected Logger log = Logger.getLogger(EmployeeAppMgm.class);

	public EmployeeAppMgm() {
		super();
	}

	public EmployeeAppMgm(Map<String, Object> params) {
		super();
		this.params = params;
	}

	/**
	 * Launch the application
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			EmployeeAppMgm window = new EmployeeAppMgm();
			window.open();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Open the window
	 */
	public void open() {
		final Display display = Display.getDefault();
		createContents();
		shell.open();
		shell.layout();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
	}

	/**
	 * Create contents of the window
	 */
	protected void createContents() {
		shell = new Shell();
		shell.setBackgroundImage(SWTResourceManager.getImage(
				EmployeeAppMgm.class, "/img/main.jpg"));
		shell.setImage(SWTResourceManager.getImage(EmployeeAppMgm.class,
				"/img/iMac OSX.png"));
		shell.setFont(SWTResourceManager.getFont("", 12, SWT.NONE));
		shell.setBackgroundMode(SWT.INHERIT_DEFAULT);
		shell.setSize(1280, 800);
		shell.setText("Update Employee");

		initScreen(shell, getParams());

		final Composite composite = new Composite(shell, SWT.NONE);
		composite.setBounds(0, 50, 892, 513);

		final Label messageLabel = new Label(composite, SWT.NONE);
		messageLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		messageLabel.setText("Please update the employee details below");
		messageLabel.setBounds(10, 3, 872, 20);

		final Label usernameLabel = new Label(composite, SWT.NONE);
		usernameLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		usernameLabel.setText("Username");
		usernameLabel.setBounds(10, 40, 75, 20);

		final Label passwordLabel = new Label(composite, SWT.NONE);
		passwordLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		passwordLabel.setText("Password");
		passwordLabel.setBounds(10, 74, 70, 20);

		final Label confirmPasswordLabel = new Label(composite, SWT.NONE);
		confirmPasswordLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		confirmPasswordLabel.setText("Confirm Password");
		confirmPasswordLabel.setBounds(10, 106, 130, 20);

		final Label nameLabel = new Label(composite, SWT.NONE);
		nameLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		nameLabel.setText("Name");
		nameLabel.setBounds(10, 185, 45, 20);

		final Label codeLabel = new Label(composite, SWT.NONE);
		codeLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		codeLabel.setText("Code");
		codeLabel.setBounds(10, 221, 40, 20);

		final Label icLabel = new Label(composite, SWT.NONE);
		icLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		icLabel.setText("IC");
		icLabel.setBounds(10, 252, 20, 20);

		final Label birthdateLabel = new Label(composite, SWT.NONE);
		birthdateLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		birthdateLabel.setText("Birthdate");
		birthdateLabel.setBounds(10, 287, 65, 20);

		final Label phoneLabel = new Label(composite, SWT.NONE);
		phoneLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		phoneLabel.setText("Phone");
		phoneLabel.setBounds(10, 325, 50, 20);

		final Label emailLabel = new Label(composite, SWT.NONE);
		emailLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		emailLabel.setText("Email");
		emailLabel.setBounds(10, 364, 40, 20);

		final Label addressLabel = new Label(composite, SWT.NONE);
		addressLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		addressLabel.setText("Address");
		addressLabel.setBounds(10, 396, 60, 20);

		final Text text = new Text(composite, SWT.BORDER);
		text.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text.setEditable(false);
		text.setToolTipText("user_username");
		text.setBounds(165, 37, 333, 30);

		final Text text_1 = new Text(composite, SWT.BORDER | SWT.PASSWORD);
		text_1.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text_1.setToolTipText("user_password");
		text_1.setBounds(165, 71, 333, 30);

		final Text text_2 = new Text(composite, SWT.BORDER | SWT.PASSWORD);
		text_2.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text_2.setToolTipText("user_cpassword");
		text_2.setBounds(165, 103, 333, 30);

		final Text text_3 = new Text(composite, SWT.BORDER);
		text_3.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text_3.setToolTipText("emp_name");
		text_3.setBounds(165, 182, 333, 30);

		final Text text_4 = new Text(composite, SWT.BORDER);
		text_4.setEditable(false);
		text_4.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text_4.setToolTipText("emp_code");
		text_4.setBounds(165, 218, 333, 30);

		final Text text_5 = new Text(composite, SWT.BORDER);
		text_5.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text_5.setToolTipText("emp_ic");
		text_5.setBounds(165, 252, 333, 30);

		final Text text_6 = new Text(composite, SWT.BORDER);
		text_6.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text_6.setToolTipText("emp_birthdate");
		text_6.setBounds(165, 287, 247, 30);

		final Text text_7 = new Text(composite, SWT.BORDER);
		text_7.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text_7.setToolTipText("emp_phone");
		text_7.setBounds(165, 322, 247, 30);

		final Text text_8 = new Text(composite, SWT.BORDER);
		text_8.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text_8.setToolTipText("emp_email");
		text_8.setBounds(165, 354, 247, 30);

		final Text text_9 = new Text(composite, SWT.WRAP | SWT.V_SCROLL
				| SWT.MULTI | SWT.BORDER);
		text_9.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text_9.setToolTipText("emp_address");
		text_9.setBounds(165, 396, 333, 107);

		final Button updateEmployeeButton = new Button(shell, SWT.NONE);
		updateEmployeeButton.setImage(SWTResourceManager.getImage(
				EmployeeAppMgm.class, "/img/Edit.png"));
		updateEmployeeButton.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		updateEmployeeButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				try {
					User user = new UserModel();
					Employee employee = new EmployeeModel();

					Session session = HibernateUtil.getSessionFactory()
							.getCurrentSession();
					user = (User) setModel(composite, "user", user);
					employee = (Employee) setModel(composite, "emp", employee);

					user = (User) session.get(UserModel.class, user.getId());
					employee = (Employee) session.get(EmployeeModel.class,
							employee.getId());
					// TODO : try to avoid doing twice, is slower
					user = (User) setModel(composite, "user", user);
					employee = (Employee) setModel(composite, "emp", employee);

					log.debug(user.getClass().getSimpleName() + " : "
							+ user.getValues().toString());
					log.debug(employee.getClass().getSimpleName() + " : "
							+ employee.getValues().toString());

					List<String> errors = EmployeeAppNew.validateForm(user,
							employee, text_2.getText(), combo.getText());
					if (errors.isEmpty()) {
						user = (User) preUpdate(user, getParams());
						employee = (Employee) preUpdate(employee, getParams());

						user.setRole(doRetrieveRoleByName(combo.getText()));
						
						int rowCount = doUpdate(employee, user);

						if (rowCount >= 2) {
							message(getShell(), "Update Success.",
									"Employee updated successfully.");

							getParams().put(AppConstant.APPCTRL,
									EmployeeAppCtrl.EMP_CTRL);
							getParams().put(AppConstant.ACTION,
									EmployeeAppCtrl.EMP_ENQ);
							getShell().close();
						}
					} else {
						message(getShell(), "Update Error.", errors,
								SWT.ICON_ERROR | SWT.OK);
					}
				} catch (Exception ex) {
					message(getShell(), "Update Error", ex.getMessage(),
							SWT.ICON_ERROR | SWT.OK);
					log.error(ex.getMessage(), ex);
				}
			}
		});
		updateEmployeeButton.setText("Update");
		updateEmployeeButton.setBounds(165, 569, 90, 30);

		final Button resetButton = new Button(shell, SWT.NONE);
		resetButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				getShell().close();
			}
		});
		resetButton.setImage(SWTResourceManager.getImage(EmployeeAppMgm.class,
				"/img/Refresh.png"));
		resetButton.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		resetButton.setText("Reset");
		resetButton.setBounds(261, 569, 80, 30);

		final Text text_10 = new Text(composite, SWT.BORDER);
		text_10.setVisible(false);
		text_10.setToolTipText("user_id");
		text_10.setBounds(532, 44, 170, 25);

		final Text text_11 = new Text(composite, SWT.BORDER);
		text_11.setVisible(false);
		text_11.setToolTipText("emp_id");
		text_11.setBounds(532, 189, 170, 25);

		final Text text_12 = new Text(composite, SWT.BORDER);
		text_12.setVisible(false);
		text_12.setBounds(532, 71, 170, 25);
		text_12.setToolTipText("user_status");

		final Text text_13 = new Text(composite, SWT.BORDER);
		text_13.setVisible(false);
		text_13.setBounds(532, 218, 170, 25);
		text_13.setToolTipText("emp_status");

		final Button pickDateButton = new Button(composite, SWT.NONE);
		pickDateButton.setImage(SWTResourceManager.getImage(
				EmployeeAppMgm.class, "/img/Calendar.png"));
		pickDateButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				pickDate(getShell(), text_6);
			}
		});
		pickDateButton.setBounds(416, 294, 30, 30);

		final Label roleaLabel = new Label(composite, SWT.NONE);
		roleaLabel.setBounds(532, 106, 35, 20);
		roleaLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		roleaLabel.setText("Role");

		combo = new Combo(composite, SWT.READ_ONLY);
		combo.setBounds(593, 103, 259, 28);
		combo.select(0);
		combo.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));

		//
		buildStandardMenu(getShell(), getParams(), EmployeeAppCtrl.EMP_CTRL,
				EmployeeAppCtrl.EMP_ENQ);
		populateControls(composite, text_2, combo);
	}

	private void populateControls(Composite composite, Text cpassword,
			Combo roleCombo) {
		if (getParams().get(EmployeeAppCtrl.EMP_ID) == null) {
			getParams().put(EmployeeAppCtrl.EMP_MSG,
					"Unable to display employee, employee ID not found.");

			getParams().put(AppConstant.APPCTRL, EmployeeAppCtrl.EMP_CTRL);
			getParams().put(AppConstant.ACTION, EmployeeAppCtrl.EMP_ENQ);
			getShell().close();
		}

		try {
			Long id = (Long) getParams().get(EmployeeAppCtrl.EMP_ID);

			Session session = HibernateUtil.getSessionFactory()
					.getCurrentSession();
			session.beginTransaction();

			Employee employee = (Employee) session.get(EmployeeModel.class, id);
			if (employee != null) {
				setControls(composite, "emp", employee);

				User user = (User) session.createCriteria(UserModel.class).add(
						Expression.eq(User.FLD_EMPLOYEE, employee))
						.uniqueResult();
				if (user != null) {
					setControls(composite, "user", user);
					cpassword.setText(user.getPassword());
					populateRoleCombo(combo, user.getRole());
				}
			}
		} catch (Exception e) {
			getParams().put(EmployeeAppCtrl.EMP_MSG, e.getMessage());
			log.error(e.getMessage(), e);

			getParams().put(AppConstant.APPCTRL, EmployeeAppCtrl.EMP_CTRL);
			getParams().put(AppConstant.ACTION, EmployeeAppCtrl.EMP_ENQ);
			getShell().close();
		}
	}

	private int doUpdate(Employee employee, User user) throws Exception {
		int rowCount = 0;
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		try {
			session.beginTransaction();

			session.saveOrUpdate(employee);
			log.debug(employee.getClass().getSimpleName() + " : "
					+ employee.getValues().toString());
			rowCount++;

			session.saveOrUpdate(user);
			log.debug(user.getClass().getSimpleName() + " : "
					+ user.getValues().toString());
			rowCount++;

			session.getTransaction().commit();
		} catch (Exception e) {
			session.getTransaction().rollback();
			throw e;

		}
		return rowCount;
	}

	private void populateRoleCombo(Combo combo, Role role) {
		try {
			Session session = HibernateUtil.getSessionFactory()
					.getCurrentSession();
			session.beginTransaction();

			List<Role> roles = session.createCriteria(RoleModel.class).add(
					Expression.eq(Role.FLD_STATUS, AppConstant.STATUS_ACTIVE))
					.list();
			if (roles != null && !roles.isEmpty()) {
				combo.removeAll();
				for (Iterator<Role> iter = roles.iterator(); iter.hasNext();) {
					Role ro = iter.next();
					combo.add(ro.getName());
				}
				combo.select(0);
				
				if (role != null && role.getId() != null) {
					String[] items = combo.getItems();
					if (items != null && items.length > 0) {
						for (int i=0; i<items.length; i++) {
							if (items[i].equals(role.getName())) {
								combo.select(i);
								break;
							}
						}
					}
				}
			}
		} catch (Exception e) {
			log.error("Unable to populate role combo.", e);
		}
	}
	
	private Role doRetrieveRoleByName(String name) {
		Role role = null;
		try {
			Session session = HibernateUtil.getSessionFactory()
					.getCurrentSession();
			session.beginTransaction();

			List<Role> roles = session.createCriteria(RoleModel.class).add(
					Expression.eq(Role.FLD_NAME, name)).setMaxResults(1).list();
			if (roles != null && !roles.isEmpty()) {
				role = roles.get(0);
			}
		} catch (Exception e) {
			log.error("Unable to retrieve role by name.", e);
		}
		return role;
	}

	public Shell getShell() {
		return shell;
	}
}
